package com.zs.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zs.blog.converter.AuthorityConverter;
import com.zs.blog.dao.IAuthorityMapper;
import com.zs.blog.exception.BusinessException;
import com.zs.blog.model.dto.AuthorityDTO;
import com.zs.blog.model.dto.AuthorityEditDTO;
import com.zs.blog.model.dto.AuthoritySearchDTO;
import com.zs.blog.model.entity.Authority;
import com.zs.blog.model.vo.AuthorityLabelListVO;
import com.zs.blog.model.vo.AuthorityListVO;
import com.zs.blog.model.vo.PageInfoVO;
import com.zs.blog.service.IAuthorityService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Title: IAuthorityServiceImpl
 * @Author zs
 * @Package com.zs.blog.service.impl
 * @Date 2025/9/2 21:20
 * @description: 系统资源权限服务层接口实现类
 */
@Service
public class IAuthorityServiceImpl extends ServiceImpl<IAuthorityMapper, Authority> implements IAuthorityService {

    public IAuthorityMapper authorityMapper;

    @Autowired
    public IAuthorityServiceImpl(IAuthorityMapper authorityMapper) {
        this.authorityMapper = authorityMapper;
    }


    /**
     * 获取系统资源权限层级信息列表
     *
     * @return 系统资源权限层级信息列表
     */
    @Override
    public List<AuthorityLabelListVO> listAuthorityLevelInfo() {
        // 查询所有系统资源权限信息
        LambdaQueryWrapper<Authority> lqw = new LambdaQueryWrapper<>();
        List<Authority> allAuthority = authorityMapper.selectList(lqw);

        // 数据映射
        List<AuthorityLabelListVO> authorityLabelListVOS = AuthorityConverter.INSTANCE.authorityList2AuthorityLabelListVO(allAuthority);

        // 获取系统资源权限顶层说明
        List<AuthorityLabelListVO> topAuthorityLevel = new ArrayList<>();
        authorityLabelListVOS.forEach(item -> {
            if (item.getParentId() == 0 && item.getMenuId() == 0) {
                topAuthorityLevel.add(item);
            }
        });

        // 构建子集映射
        Map<Long, List<AuthorityLabelListVO>> subAuthorityLevel = authorityLabelListVOS.stream()
                .filter(item -> {
                    return item.getParentId() != 0 && item.getMenuId() != 0;
                }).collect(Collectors.groupingBy(AuthorityLabelListVO::getParentId));

        // 构建层级树
        for (AuthorityLabelListVO authorityLabelListVO : authorityLabelListVOS) {
            List<AuthorityLabelListVO> authorityLabelList = subAuthorityLevel.get(authorityLabelListVO.getId());
            if (authorityLabelList != null) {
                authorityLabelListVO.setChildren(authorityLabelList);
            }
        }

        return topAuthorityLevel;
    }

    /**
     * 获取分页的权限列表信息
     *
     * @param pageNum  页码
     * @param pageSize 每页数据
     * @return 分页的系统资源权限列表
     */
    @Override
    public PageInfoVO<AuthorityListVO> listAuthorityWithPagination(Integer pageNum, Integer pageSize) {
        // 分页对象
        IPage<AuthorityDTO> page = new Page<>(pageNum, pageSize);

        // 查询数据
//        LambdaQueryWrapper<Authority> lqw = new LambdaQueryWrapper<>();
//        lqw.eq(Authority::getIsDeleted,0);
        /*
            这里使用QueryWrapper对象是为了在生成的SQL中避免is_deleted字段有歧义
            （两个表都有is_deleted并且在sql中都有使用）
            改进方向: 利用mybatis xml调用Java静态方法对sql片段进行预处理，这样可以使用lqw了
         */
        // todo
        QueryWrapper<Authority> qw = new QueryWrapper<>();
//        qw.eq("t1.is_deleted", 0);
        List<AuthorityDTO> authorityDTOS = authorityMapper.listAuthorityWithPagination(page, qw);

        // 数据转换
        List<AuthorityListVO> authorityListVOS = new ArrayList<>();
        authorityDTOS.forEach(item -> authorityListVOS.add(AuthorityConverter.INSTANCE.authorityDTO2AuthorityListVO(item)));

        // 返回对象
        PageInfoVO<AuthorityListVO> pageInfo = new PageInfoVO<>();
        pageInfo.setTotal(page.getTotal());
        pageInfo.setItems(authorityListVOS);
        return pageInfo;
    }

    /**
     * 新增权限信息
     *
     * @param authorityEditDTO 接收权限新增或修改的参数实体类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAuthority(AuthorityEditDTO authorityEditDTO) {
        if (authorityEditDTO != null) {
            // 判断是否有相同的权限
            LambdaQueryWrapper<Authority> lqw = new LambdaQueryWrapper<>();
            lqw.eq(Authority::getAuthorityDescription, authorityEditDTO.authorityDescription)
                    .eq(Authority::getAuthorityDescriptor, authorityEditDTO.getAuthorityDescriptor());
            Authority authority = authorityMapper.selectOne(lqw);

            if (authority != null) {
                throw new BusinessException("已有相同权限");
            }

            // 数据映射
            Authority insertEntity = AuthorityConverter.INSTANCE.authorityEditDTO2Authority(authorityEditDTO);
            // 插入数据
            authorityMapper.insert(insertEntity);
        }
    }

    /**
     * 删除权限信息
     *
     * @param authorityIds 要删除的数据ID列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAuthority(List<Long> authorityIds) {
        if (authorityIds == null || authorityIds.isEmpty()) {
            throw new BusinessException("没有需要删除的记录！");
        }
        // 检验记录是否存在 参数提供的ID可能不存在
        List<Authority> authorities = authorityMapper.selectBatchIds(authorityIds);
        // 获取数据库中查到的数据的ID列表 查出来的结果直接就是两者的交集,查出来的ID一定是小于等于传来的
        List<Long> daoValue = authorities.stream().map(Authority::getId).toList();

        // todo 对in里面的ID进行切分 分批更新

        LambdaUpdateWrapper<Authority> luw = new LambdaUpdateWrapper<>();
        luw.set(Authority::getIsDeleted, 1)
                .in(Authority::getId, daoValue);
        authorityMapper.update(luw);
    }

    /**
     * 通过搜索条件查询分页的角色列表
     *
     * @param authoritySearchDTO 权限查询条件参数接收类
     * @return 分页的权限列表
     */
    @Override
    public PageInfoVO<AuthorityListVO> listAuthorityBySearchCondition(AuthoritySearchDTO authoritySearchDTO) {
        // 分页对象
        IPage<AuthorityDTO> page = new Page<>(authoritySearchDTO.getPageNum(), authoritySearchDTO.getPageSize());

        // 查询数据
        LambdaQueryWrapper<Authority> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StringUtils.isNotBlank(authoritySearchDTO.getAuthorityDescription()), Authority::getAuthorityDescription, authoritySearchDTO.getAuthorityDescription())
                .eq(StringUtils.isNotBlank(authoritySearchDTO.getAuthorityDescriptor()), Authority::getAuthorityDescriptor, authoritySearchDTO.getAuthorityDescriptor())
                .eq(authoritySearchDTO.getAuthorityMenuId() != null && authoritySearchDTO.getAuthorityMenuId() > 0L, Authority::getMenuId, authoritySearchDTO.getAuthorityMenuId());
        if (authoritySearchDTO.getStartTime() != null && authoritySearchDTO.getEndTime() != null) {
            lqw.between(Authority::getCreateTime, authoritySearchDTO.getStartTime(), authoritySearchDTO.getEndTime());
        }
        List<AuthorityDTO> listAuthority = authorityMapper.listAuthorityBySearchCondition(lqw,page);

        // 数据映射
        List<AuthorityListVO> res = listAuthority.stream().map(AuthorityConverter.INSTANCE::authorityDTO2AuthorityListVO).toList();

        PageInfoVO<AuthorityListVO> pageInfo = new PageInfoVO<>();
        pageInfo.setTotal(page.getTotal());
        pageInfo.setItems(res);
        return pageInfo;
    }
}
